package jch.learn.java.advanced.chapter1_stream.collecting;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

// 收集结果
public class CollectingResults {

    public static Stream<String> noVowels() throws URISyntaxException, IOException {
        String contents = new String(Files.readAllBytes(Paths.get(CollectingResults.class.getResource("/gutenberg/alice30.txt").toURI())), StandardCharsets.UTF_8);
        List<String> wordList = Arrays.asList(contents.split("\\PL+"));
        Stream<String> words = wordList.stream();
        return words.map(s -> s.replaceAll("[aeiouAEIOU]",""));
    }

    public static <T> void show(String label, Set<T> set){
        System.out.println(label + ": " + set.getClass().getName());
        System.out.println("[" + set.stream().limit(10).map(Object::toString).collect(Collectors.joining(", ")) + "]");
    }

    public static void main(String[] args) throws IOException, URISyntaxException {
        Iterator<Integer> iter = Stream.iterate(0,n -> n+1).limit(10).iterator();
        while(iter.hasNext()) {
            System.out.println(iter.next());
        }

        // java.util.stream.Stream
        // Object[] toArray() 产生一个对象数组。 终结操作
        Object[] numbers = Stream.iterate(0,n -> n + 1).limit(10).toArray();
        System.out.println("Object array:" + numbers);

        try {
            Integer number = (Integer) numbers[0];
            System.out.println("number: " + number);
            System.out.println("The following statement throws an exception:");
            Integer[] numbers2 = (Integer[]) numbers;
        } catch (ClassCastException ex){
            System.out.println(ex);
        }

        // java.util.stream.Stream
        // <A> A[] toArray(IntFunction<A[]> generator)  产生一个依据传入引用A[]::new的A类型数组。 终结操作
        Integer[] numbers3 = Stream.iterate(0,n -> n+1).limit(10).toArray(Integer[]::new);
        System.out.println("Integer array: " + numbers3);

        // java.util.stream.Stream
        // <R,A> R collect(Collector<? super T,A,R> collector)  使用给定的收集器来收集当前流中的元素。
        // java.util.stream.Collectors
        // static <T> Collector<T,?,List<T>> toList()   产生一个将元素收集到列表中的收集器
        // static <T> Collector<T,?,Set<T>> toSet() 产生一个将元素收集到集合中的收集器
        Set<String> noVowelSet = noVowels().collect(Collectors.toSet());
        show("noVowelSet",noVowelSet);

        // java.util.stream.Collectors
        // static <T,C extends Collection<T>> Collector<T,?,C> toCollection(Supplier<C> collectionFactory)
        // 产生一个将元素收集到任意集合中的收集器，可以传递一个如TreeSet::new的构造器引用
        TreeSet<String> noVowelTreeSet = noVowels().collect(Collectors.toCollection(TreeSet::new));
        show("noVowelSet",noVowelTreeSet);

        // java.util.stream.Collectors
        // static Collectors<CharSequence,?,String> joining()   产生一个将元素连接成字符串的收集器
        // static Collectors<CharSequence,?,String> joining(CharSequence delimiter) 产生一个将元素连接为字符串的收集器，
        //  元素之间使用给定分隔符分隔。
        // static Collectors<CharSequence,?,String> joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
        //  产生一个将元素连接为字符串的收集器，元素之间使用指定分隔符，第一个字符串之前可以有前缀，最后一个字符串可以有后缀。若无指定则皆为空。
        String result = noVowels().limit(10).collect(Collectors.joining());
        System.out.println("Joining: " + result);

        result = noVowels().limit(10).collect(Collectors.joining(", "));
        System.out.println("Joining with commas: " + result);

        // java.util.stream.Collectors
        // static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)
        // 产生能够生成IntSummaryStatistics对象的收集器，通过它可以获取将mapper应用于元素后所产生结果的个数、总和、平均值、最大值和最小值。
        // static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)
        // static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)
        IntSummaryStatistics summary = noVowels().collect(Collectors.summarizingInt(String::length));
        // IntSummaryStatistics，LongSummaryStatistics，DoubleSummaryStatistics
        // long getCount()  产生汇总后的元素个数
        // (int|long|double) getSum()   产生汇总后的元素的总和，没有任何元素时返回0.
        // double getAverage()  产生汇总后的元素的平均值，没有任何元素时返回0
        // (int|long|double) getMax()   产生汇总后的元素的最大值，没有任何元素时返回(Integer|Long|Double).MAX_VALUE
        // (int|long|double) getMin()   产生汇总后的元素的最小值，没有任何元素时返回(Integer|Long|Double).MIN_VALUE
        double averageWordLength = summary.getAverage();
        double maxWordLength = summary.getMax();
        System.out.println("Average word length: " + averageWordLength);
        System.out.println("Max word length: " + maxWordLength);
        System.out.println("forEach: ");

        // java.util.stream.Stream
        // void forEach(Consumer<? super T> action) 遍历流上的每个元素。是一个终结操作
        noVowels().limit(10).forEach(System.out::println);
    }
}
